package com.xiaolei.fastnio.library.Workers

import com.xiaolei.fastnio.library.Client.Session
import com.xiaolei.fastnio.library.Factorys.IClientAdapterFactory
import java.nio.ByteBuffer
import java.nio.channels.SelectionKey
import java.nio.channels.Selector
import java.nio.channels.SocketChannel
import java.util.concurrent.LinkedBlockingQueue

/**
 * 读取客户端发过来的数据
 * @param readQueue 等待读取数据的阻塞队列
 * @param readSelector 读取数据的选择器
 * @param clientFactory 客户端与sessionid对应的工厂类
 * @param bufferSize 读取数据的缓冲大小
 */
class ClientReadWorker(private val readQueue: LinkedBlockingQueue<SelectionKey>,
                       private val readSelector: Selector,
                       private val clientFactory: IClientAdapterFactory<*>,
                       private val bufferSize: Int) : Runnable
{
    private lateinit var readBuffer: ByteBuffer

    override fun run()
    {
        readBuffer = ByteBuffer.allocate(bufferSize)
        while (readSelector.isOpen)
        {
            val key = readQueue.take()
            val session = key.attachment() as Session
            val clientChannel = key.channel() as SocketChannel
            val clientAdapter = clientFactory.get(session.sessionId)
            try
            {
                // 读取长度
                var readLen = clientChannel.read(readBuffer)
                while (readLen > 0)
                {
                    clientAdapter.onReceive(session, readBuffer.array(), readLen)
                    readBuffer.clear()
                    readLen = if (clientChannel.isOpen)
                    {
                        clientChannel.read(readBuffer)
                    } else
                    {
                        0
                    }
                }
                // 如果读取的长度为-1 ，那么就是掉线了，需要响应关闭事件
                if (readLen < 0 || !clientChannel.isOpen)
                {
                    session.isAlive = false
                    clientChannel.close()
                    clientAdapter.onClose(session)
                    clientFactory.remove(session.sessionId)
                } else
                {
                    // 重新注册回去，以便下次继续响应
                    clientChannel.register(readSelector, SelectionKey.OP_READ, session)
                    readSelector.wakeup()
                }
            } catch (e: Exception)
            {
                // session.isAlive = false
                // clientChannel.close()
                // clientAdapter.onClose(session)
                // clientFactory.remove(session.sessionId)
                e.printStackTrace()
            }
        }
    }
}